package com.zerocarbon.framework.db.mybatis.typehandler;

import com.zerocarbon.framework.common.utils.AesUtil;
import org.apache.ibatis.type.Alias;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Base64;

/**
 * 用户信息字段加密
 *
 * @author yangtao
 * 2020.11.02
 */
@Alias("fieldAccountEncrypt")
public class FieldAccountEncryptTypeHandler extends BaseTypeHandler<CharSequence> {

    /**
     * 填充方式
     */
    private static final String CIPHER_INSTANCE = "AES/CBC/PKCS7Padding";

    /**
     * 偏移量
     */
    private static final byte[] iv = new byte[]{-61, -113, -102, 119, 117, 24, 0, 4, -43, -45, -91, -85, 101, -56, -31, -108};

    /**
     * AES密钥，后台改成从配置文件中读取，各环境可以设置成不一样
     */
    private final static String keyHexStr = "FE546AFD40BF44E9A8222B32AAB729FE";

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, CharSequence parameter, JdbcType jdbcType) throws SQLException {
        if (parameter == null) {
            ps.setString(i, null);
        } else {
            ps.setString(i, encrypt(parameter.toString()));
        }
    }

    @Override
    public CharSequence getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return decrypt(rs.getString(columnName));
    }

    @Override
    public CharSequence getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return decrypt(rs.getString(columnIndex));
    }

    @Override
    public CharSequence getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return decrypt(cs.getString(columnIndex));
    }

    /**
     * AES密钥加密
     *
     * @param content
     * @return
     */
    public static String encrypt(String content) {
        byte[] result = AesUtil.encrypt(content.getBytes(), keyHexStr.getBytes(), CIPHER_INSTANCE, true, iv);
        return Base64.getEncoder().encodeToString(join(iv, result));
    }

    /**
     * AES密钥解密
     *
     * @param content
     * @return
     */
    public static String decrypt(String content) {
        if(content==null || "".equals(content)){
            return null;
        }
        //字符串开头如果不是 w4+ad3U 说明不是密文则不需要解密
        if(!content.startsWith("w4+ad3U")){
            return content;
        }
        byte[] decode = Base64.getDecoder().decode(content);
        byte[] data = new byte[decode.length - 16];
        System.arraycopy(decode, 16, data, 0, data.length);
        byte[] result = AesUtil.decrypt(data, keyHexStr.getBytes(), CIPHER_INSTANCE, true, iv);
        return new String(result);
    }

    public static byte[] join(byte[] bs1, byte[] bs2) {
        byte[] r = new byte[bs1.length + bs2.length];
        System.arraycopy(bs1, 0, r, 0, bs1.length);
        System.arraycopy(bs2, 0, r, bs1.length, bs2.length);
        return r;
    }

    //public static void main(String[] args) {
        //String str1 = encrypt("anvvv");
        //String str1="w4+ad3UYAATV06WrZcjhlCDc9kqKE7rcpX5jPVEqpvo=";
        //String str1 = "w4+ad3UYAATV06WrZcjhlJItsZoSuayvkmF+Ozuj0wI=";
        //System.out.println("str1:"+str1);
        //System.out.println("v:"+decrypt(str1));
    //}
}
